package com.tms.permission.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tms.permission.mapper.SystemPermissionMapper;
import com.tms.permission.utils.RedisUtil;
import com.tms.systemPermission.bean.SystemPermission;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * 权限数据同步服务
 */
@Service
@Slf4j
public class PermissionSyncService {

    private static final Logger logger = LoggerFactory.getLogger(PermissionSyncService.class);

    private static final String SYNC_LOCK_KEY = "permission:sync:lock";
    private static final String LAST_SYNC_TIME_KEY = "permission:sync:last_time";
    private static final int LOCK_TIMEOUT = 60; // 锁超时时间，单位秒
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    private SystemPermissionMapper systemPermissionMapper;

    /**
     * 全量同步权限数据到Redis
     * 每天凌晨2点执行
     */
    @Scheduled(cron = "0 0 2 * * ?")
    @Transactional(readOnly = true)
    public void fullSync() {
        String taskName = "权限数据全量同步";
        boolean locked = tryLock(SYNC_LOCK_KEY, LOCK_TIMEOUT);

        if (!locked) {
            log.warn("{}任务正在执行，跳过本次调度", taskName);
            return;
        }

        try {
            log.info("开始执行{}任务", taskName);
            //数据库读取所有接口权限
            List<SystemPermission> systemPermissions = systemPermissionMapper.selectList(new LambdaQueryWrapper<SystemPermission>()
                    .eq(SystemPermission::getPermissionType, 3)
                    .eq(SystemPermission::getStatus, 1)
                    .eq(SystemPermission::getIsDeleted, 0));
            for (SystemPermission systemPermission : systemPermissions){
                //全部更新前先初始化  //TODO 考虑优化 风险太高
//                redisUtil.delete("permission:apiList");
                //permission:api:{path}:{method} -> 权限编码
                redisUtil.set("permission:apiList:"+systemPermission.getRequestPath()
                        +":"+systemPermission.getRequestMethod(),systemPermission.getPermissionCode());
            }
            // 更新同步时间
            updateSyncTime();
            log.info("{}任务执行完成", taskName);
        } catch (Exception e) {
            log.error("{}任务执行异常", taskName, e);
        } finally {
            // 释放锁
            releaseLock(SYNC_LOCK_KEY);
        }
    }

    /**
     * 增量同步权限数据到Redis
     * 每小时执行一次
     */
    @Scheduled(cron = "0 0 * * * ?")
    @Transactional(readOnly = true)
    public void incrementalSync() {
        String taskName = "权限数据增量同步";
        boolean locked = tryLock(SYNC_LOCK_KEY, LOCK_TIMEOUT);

        if (!locked) {
            log.warn("{}任务正在执行，跳过本次调度", taskName);
            return;
        }

        try {
            log.info("开始执行{}任务", taskName);
            // 获取上次同步时间
            String lastSyncTimeStr = (String) redisTemplate.opsForValue().get(LAST_SYNC_TIME_KEY);

            // TODO: 根据上次同步时间，实现从数据库读取增量权限数据的逻辑

            // 更新同步时间
            updateSyncTime();
            log.info("{}任务执行完成", taskName);
        } catch (Exception e) {
            log.error("{}任务执行异常", taskName, e);
        } finally {
            // 释放锁
            releaseLock(SYNC_LOCK_KEY);
        }
    }

    /**
     * 尝试获取分布式锁
     */
    private boolean tryLock(String lockKey, long timeoutSeconds) {
        Boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, "LOCKED", timeoutSeconds, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

    /**
     * 释放分布式锁
     */
    private void releaseLock(String lockKey) {
        redisTemplate.delete(lockKey);
    }

    /**
     * 更新最后同步时间
     */
    private void updateSyncTime() {
        String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DATE_FORMAT));
        redisTemplate.opsForValue().set(LAST_SYNC_TIME_KEY, now);
    }
}
